package com.yupi.springbootinit.statemachine.permission;

import com.yupi.springbootinit.statemachine.core.StateContext;
import com.yupi.springbootinit.statemachine.enums.RoleEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 权限管理器
 * 基于部门ID的权限控制，简化权限管理逻辑
 */
@Slf4j
@Component
public class PermissionManager {
    
    /**
     * 部门ID常量定义
     */
    public static final Long ADMIN_DEPT_ID = 1L;        // 管理员部门
    public static final Long PROJECT_DEPT_ID = 2L;      // 项目部
    public static final Long ENGINEERING_DEPT_ID = 3L;  // 工程部
    public static final Long PMC_DEPT_ID = 4L;          // PMC部门
    public static final Long PRODUCTION_DEPT_ID = 5L;   // 生产部
    public static final Long QUALITY_DEPT_ID = 6L;      // 品质部
    
    /**
     * 状态转换权限映射表
     * 定义每种状态转换需要的部门权限
     */
    private static final Map<String, Set<Long>> STATE_TRANSITION_DEPT_PERMISSIONS = new HashMap<>();
    
    static {
        initializeStateTransitionPermissions();
    }
    
    /**
     * 初始化状态转换权限映射
     */
    private static void initializeStateTransitionPermissions() {
        // 订单状态转换权限
        STATE_TRANSITION_DEPT_PERMISSIONS.put("ORDER:CREATED->ROUTING_PUBLISHED", 
            Set.of(ENGINEERING_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("ORDER:ROUTING_PUBLISHED->SCHEDULE_PUBLISHED", 
            Set.of(PMC_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("ORDER:SCHEDULE_PUBLISHED->IN_PRODUCTION", 
            Set.of(PRODUCTION_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("ORDER:IN_PRODUCTION->IN_INSPECTION", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("ORDER:IN_INSPECTION->COMPLETED", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        
        // 工艺单状态转换权限
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PROCESS_SHEET:EDITING->PUBLISHED", 
            Set.of(ENGINEERING_DEPT_ID, ADMIN_DEPT_ID));
        
        // 生产排期状态转换权限
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PRODUCTION_SCHEDULE:EDITING->PUBLISHED", 
            Set.of(PMC_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PRODUCTION_SCHEDULE:PUBLISHED->ADJUSTED", 
            Set.of(PMC_DEPT_ID, ADMIN_DEPT_ID));
        
        // 工序实例状态转换权限
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PROCESS_INSTANCE:PENDING->IN_PROGRESS", 
            Set.of(PRODUCTION_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PROCESS_INSTANCE:IN_PROGRESS->PENDING_INSPECTION", 
            Set.of(PRODUCTION_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PROCESS_INSTANCE:PENDING_INSPECTION->IN_INSPECTION", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PROCESS_INSTANCE:IN_INSPECTION->COMPLETED", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PROCESS_INSTANCE:IN_INSPECTION->UNQUALIFIED_REWORK", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("PROCESS_INSTANCE:UNQUALIFIED_REWORK->IN_PROGRESS", 
            Set.of(PRODUCTION_DEPT_ID, ADMIN_DEPT_ID));
        
        // 质检任务状态转换权限
        STATE_TRANSITION_DEPT_PERMISSIONS.put("QUALITY_INSPECTION:PENDING->IN_PROGRESS", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("QUALITY_INSPECTION:IN_PROGRESS->QUALIFIED", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("QUALITY_INSPECTION:IN_PROGRESS->UNQUALIFIED", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("QUALITY_INSPECTION:QUALIFIED->COMPLETED", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
        STATE_TRANSITION_DEPT_PERMISSIONS.put("QUALITY_INSPECTION:UNQUALIFIED->COMPLETED", 
            Set.of(QUALITY_DEPT_ID, ADMIN_DEPT_ID));
    }
    
    /**
     * 根据用户ID获取用户部门ID
     */
    public Long getUserDepartmentId(Long userId) {
        // TODO: 实际实现应该从数据库查询用户的部门ID
        // 这里简化实现，可以根据实际需求调整
        log.debug("获取用户[{}]的部门ID", userId);
        
        // 简化实现：根据用户ID范围分配部门
        if (userId == 1L) {
            return ADMIN_DEPT_ID;
        } else if (userId >= 2L && userId <= 10L) {
            return PROJECT_DEPT_ID;
        } else if (userId >= 11L && userId <= 20L) {
            return ENGINEERING_DEPT_ID;
        } else if (userId >= 21L && userId <= 30L) {
            return PMC_DEPT_ID;
        } else if (userId >= 31L && userId <= 40L) {
            return PRODUCTION_DEPT_ID;
        } else {
            return QUALITY_DEPT_ID;
        }
    }
    
    /**
     * 根据部门ID获取角色枚举
     */
    public RoleEnum getDepartmentRole(Long departmentId) {
        if (ADMIN_DEPT_ID.equals(departmentId)) {
            return RoleEnum.ADMIN;
        } else if (PROJECT_DEPT_ID.equals(departmentId)) {
            return RoleEnum.PROJECT_DEPT;
        } else if (ENGINEERING_DEPT_ID.equals(departmentId)) {
            return RoleEnum.ENGINEERING_DEPT;
        } else if (PMC_DEPT_ID.equals(departmentId)) {
            return RoleEnum.PMC;
        } else if (PRODUCTION_DEPT_ID.equals(departmentId)) {
            return RoleEnum.PRODUCTION_DEPT;
        } else if (QUALITY_DEPT_ID.equals(departmentId)) {
            return RoleEnum.QUALITY_DEPT;
        }
        return null;
    }
    
    /**
     * 检查用户是否有权限执行指定操作
     */
    public boolean hasPermission(Long userId, String operation) {
        Long userDeptId = getUserDepartmentId(userId);
        if (userDeptId == null) {
            log.warn("无法获取用户[{}]的部门信息", userId);
            return false;
        }
        
        // 管理员拥有所有权限
        if (ADMIN_DEPT_ID.equals(userDeptId)) {
            log.debug("管理员用户[{}]拥有操作[{}]权限", userId, operation);
            return true;
        }
        
        // 根据操作类型检查部门权限
        return checkDepartmentPermission(userDeptId, operation);
    }
    
    /**
     * 验证状态转换权限
     */
    public boolean validateStateTransition(StateContext context) {
        if (context == null) {
            log.warn("状态转换上下文为空");
            return false;
        }
        
        Long userId = context.getOperatorId();
        if (userId == null) {
            log.warn("操作用户ID为空");
            return false;
        }
        
        // 构建状态转换键
        String transitionKey = buildTransitionKey(
            context.getEntityType(),
            context.getCurrentState().getCode(),
            context.getTargetState().getCode()
        );
        
        // 获取所需部门权限
        Set<Long> requiredDeptIds = STATE_TRANSITION_DEPT_PERMISSIONS.get(transitionKey);
        if (requiredDeptIds == null || requiredDeptIds.isEmpty()) {
            log.debug("状态转换[{}]无需特殊权限", transitionKey);
            return true;
        }
        
        // 检查用户部门权限
        Long userDeptId = getUserDepartmentId(userId);
        if (userDeptId == null) {
            log.warn("无法获取用户[{}]的部门信息", userId);
            return false;
        }
        
        boolean hasPermission = requiredDeptIds.contains(userDeptId);
        
        if (!hasPermission) {
            log.warn("用户[{}]部门[{}]无权限执行状态转换[{}]，需要部门权限: {}", 
                userId, userDeptId, transitionKey, requiredDeptIds);
        } else {
            log.debug("用户[{}]部门[{}]有权限执行状态转换[{}]", userId, userDeptId, transitionKey);
        }
        
        return hasPermission;
    }
    
    /**
     * 检查用户是否可以查看指定实体
     */
    public boolean canViewEntity(Long userId, String entityType, Long entityId) {
        Long userDeptId = getUserDepartmentId(userId);
        if (userDeptId == null) {
            return false;
        }
        
        // 管理员可以查看所有实体
        if (ADMIN_DEPT_ID.equals(userDeptId)) {
            return true;
        }
        
        // 项目部可以查看所有订单
        if (PROJECT_DEPT_ID.equals(userDeptId) && "ORDER".equals(entityType)) {
            return true;
        }
        
        // 其他部门只能查看与自己相关的实体
        return isEntityRelatedToDepartment(entityType, entityId, userDeptId);
    }
    
    /**
     * 检查用户是否可以操作指定实体
     */
    public boolean canOperateEntity(Long userId, String entityType, Long entityId, String operation) {
        Long userDeptId = getUserDepartmentId(userId);
        if (userDeptId == null) {
            return false;
        }
        
        // 管理员可以操作所有实体
        if (ADMIN_DEPT_ID.equals(userDeptId)) {
            return true;
        }
        
        // 检查部门是否有权限操作该类型实体
        if (!checkDepartmentEntityPermission(userDeptId, entityType, operation)) {
            return false;
        }
        
        // 检查实体是否与部门相关
        return isEntityRelatedToDepartment(entityType, entityId, userDeptId);
    }
    
    /**
     * 获取用户可执行的状态转换列表
     */
    public List<String> getAvailableTransitions(Long userId, String entityType, String currentState) {
        List<String> availableTransitions = new ArrayList<>();
        Long userDeptId = getUserDepartmentId(userId);
        
        if (userDeptId == null) {
            return availableTransitions;
        }
        
        // 遍历所有状态转换权限配置
        for (Map.Entry<String, Set<Long>> entry : STATE_TRANSITION_DEPT_PERMISSIONS.entrySet()) {
            String transitionKey = entry.getKey();
            Set<Long> requiredDeptIds = entry.getValue();
            
            // 检查是否匹配当前实体类型和状态
            if (transitionKey.startsWith(entityType + ":" + currentState + "->")) {
                // 检查用户部门是否有权限
                if (requiredDeptIds.contains(userDeptId)) {
                    String targetState = transitionKey.substring(transitionKey.lastIndexOf("->") + 2);
                    availableTransitions.add(targetState);
                }
            }
        }
        
        return availableTransitions;
    }
    
    /**
     * 构建状态转换键
     */
    private String buildTransitionKey(String entityType, String currentState, String targetState) {
        return String.format("%s:%s->%s", entityType, currentState, targetState);
    }
    
    /**
     * 检查部门权限
     */
    private boolean checkDepartmentPermission(Long departmentId, String operation) {
        // 根据部门和操作类型检查权限
        switch (operation) {
            case "CREATE_ORDER":
                return PROJECT_DEPT_ID.equals(departmentId);
            case "CREATE_PROCESS":
                return ENGINEERING_DEPT_ID.equals(departmentId);
            case "CREATE_SCHEDULE":
                return PMC_DEPT_ID.equals(departmentId);
            case "EXECUTE_PRODUCTION":
                return PRODUCTION_DEPT_ID.equals(departmentId);
            case "EXECUTE_QUALITY":
                return QUALITY_DEPT_ID.equals(departmentId);
            default:
                log.debug("未知操作类型: {}", operation);
                return false;
        }
    }
    
    /**
     * 检查部门是否有权限操作指定类型的实体
     */
    private boolean checkDepartmentEntityPermission(Long departmentId, String entityType, String operation) {
        // 简化实现：根据实体类型和部门判断权限
        switch (entityType) {
            case "ORDER":
                return PROJECT_DEPT_ID.equals(departmentId) || ADMIN_DEPT_ID.equals(departmentId);
            case "PROCESS_SHEET":
                return ENGINEERING_DEPT_ID.equals(departmentId) || ADMIN_DEPT_ID.equals(departmentId);
            case "PRODUCTION_SCHEDULE":
                return PMC_DEPT_ID.equals(departmentId) || ADMIN_DEPT_ID.equals(departmentId);
            case "PROCESS_INSTANCE":
                return PRODUCTION_DEPT_ID.equals(departmentId) || ADMIN_DEPT_ID.equals(departmentId);
            case "QUALITY_INSPECTION":
                return QUALITY_DEPT_ID.equals(departmentId) || ADMIN_DEPT_ID.equals(departmentId);
            default:
                return false;
        }
    }
    
    /**
     * 检查实体是否与部门相关
     */
    private boolean isEntityRelatedToDepartment(String entityType, Long entityId, Long departmentId) {
        // TODO: 实际实现应该查询数据库，检查实体与部门的关联关系
        // 这里简化实现，假设所有实体都与相关部门关联
        log.debug("检查实体[{}:{}]与部门[{}]的关联关系", entityType, entityId, departmentId);
        return true;
    }
    
    /**
     * 记录权限检查日志
     */
    public void logPermissionCheck(Long userId, String action, boolean result) {
        Long userDeptId = getUserDepartmentId(userId);
        RoleEnum role = getDepartmentRole(userDeptId);
        log.info("权限检查 - 用户[{}] 部门[{}] 角色[{}] 操作[{}] 结果[{}]", 
            userId, userDeptId, role, action, result ? "允许" : "拒绝");
    }
    
    /**
     * 获取部门名称
     */
    public String getDepartmentName(Long departmentId) {
        if (ADMIN_DEPT_ID.equals(departmentId)) {
            return "管理员";
        } else if (PROJECT_DEPT_ID.equals(departmentId)) {
            return "项目部";
        } else if (ENGINEERING_DEPT_ID.equals(departmentId)) {
            return "工程部";
        } else if (PMC_DEPT_ID.equals(departmentId)) {
            return "PMC";
        } else if (PRODUCTION_DEPT_ID.equals(departmentId)) {
            return "生产部";
        } else if (QUALITY_DEPT_ID.equals(departmentId)) {
            return "品质部";
        }
        return "未知部门";
    }
}